/*
 * FileName:    Grid.java
 * Description:  グリッドタグ
 * History:      2010-9-16 (廖宝俊) 1.0 Create
 */
package com.sn.system.tangs.tag;

import com.opensymphony.xwork2.util.ValueStack;

import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.sn.system.common.command.BaseConditionInfo;
import com.sn.system.common.command.Page;
import com.sn.system.common.dao.hibernate.HibernateCommonDao.HibernatePage;
import com.sn.system.common.utils.ReflectionHelper;

import org.apache.struts2.ServletActionContext;
import org.apache.struts2.components.Component;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.util.StringUtils;

public class Grid extends Component {

	/** ページデーターの名 */
    private String page;

    /** ページを分ける　action　URL */
    private String action;

    /** CSSのid */
    private String id;

    /** 検索の条件の名 */
    private String condition;

    /** 記録のユニットの名 */
    private String unit;

    /** ページを分ける　action　URL　のnamespace */
    private String namespace;

    /** CSSのClass */
    private String cssClass;

    /** Gridの幅 */
    private String width;

    /** Gridのalign */
    private String align;

    private StringBuilder str;
    private boolean hasAction;

	public Grid(ValueStack arg0) {
        super(arg0);
        this.str = new StringBuilder();
    }

    /**
     * タグ開始
     */
    public boolean start(Writer writer) {
        boolean result = super.start(writer);
		BaseConditionInfo condi=new BaseConditionInfo();
        hasAction=true;
    	if(action==null||action.equals("")){
    		hasAction=false;
        }
    	if(hasAction){
    		if(condition==null||condition.equals("")){
    			condition="condition";
            }
            else if (condition.startsWith("%{") && condition.endsWith("}")) {
            	condition = condition.substring(2, condition.length() -1);
            }
            condi=(BaseConditionInfo)this.getStack().findValue(condition)==null?new BaseConditionInfo():(BaseConditionInfo)this.getStack().findValue(condition) ;
    	}

    	if(page==null||page.equals("")){
    		page="page";
        }
        else if (page.startsWith("%{") && page.endsWith("}")) {
        	page = page.substring(2, page.length() -1);
        }
    	if(id==null||id.equals("")){
    		id="";
    	}else{
    		id="id='"+id+"'";
    	}

		cssClass = cssClass==null?"":"class='"+cssClass+"' ";
		width = width==null?"":"width='"+width+"' ";
		align = align==null?"":"align='"+align+"' ";

        pushStack();

        setActionHtml(action, hasAction, condi, str);
		str.append("<table " + id + cssClass + width + align + ">\r");

        return result;
    }

    /**
     * タグの最後に
     */
	protected boolean end(Writer writer, String body, boolean popComponentStack) {
		boolean result =  super.end(writer, body, popComponentStack);
		   Page hpage = null;

        try {
            boolean isValid = true;
            //ValueStack中から値を取りする
            if (isValid) {
                hpage=(HibernatePage)this.getStack().findValue(page);
                isValid = hpage == null ? false : true;
            }

            if (isValid) {
                Integer pageNunber = Integer.valueOf(hpage.getPageNumber());
                List pageList=hpage.getData();
                //getParam
    	        String[] proplist = StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    	        String[] titlist = StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] hreflist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] paramIdlist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] paramPropertylist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] typelist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] namelist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] valuelist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] formatlist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());

    			String[] cssClasslist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] widthlist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());
    			String[] alignlist=StringUtils.commaDelimitedListToStringArray((String)this.getStack().pop());

    			//setHeader
    			setHeader(str, titlist,cssClasslist,widthlist);

    	        setDetailed(str, pageList, proplist, hreflist, paramIdlist,
						paramPropertylist, typelist, namelist, valuelist,formatlist,
						cssClasslist,widthlist,alignlist,hpage);   
    	        
                str.append("</table>\r");
                if(hasAction){
                	 str.append("</form>\r");
                }
                
    	        for(int i=0;i<proplist.length;i++)
    	        {
    	        	if(proplist[i].equals("null")==false)
    	        	{
    	        		str.append("<input type=\"hidden\"  id=\"grid_"+proplist[i].replace(".", "_")+"_index\" value=\""+i+"\" style=\"display:none\"></input>\r");
    	        	}
    	        }
            }

            writer.write(str.toString());

        } catch (IOException ex) {
            Logger.getLogger(Grid.class.getName()).log(Level.SEVERE, null, ex);
        }
		 return result;
	}

	 /**
     * 明細の設定
     */
	private void setDetailed(StringBuilder str, List pageList,
			String[] proplist, String[] hreflist, String[] paramIdlist,
			String[] paramPropertylist, String[] typelist, String[] namelist,
			String[] valuelist,String[] formatlist,
			String[] cssClasslist,String[] widthlist,String[] alignlist,
			Page hpage) {
		int pageSize=hpage.getPageSize();
        int pageNumber=hpage.getPageNumber();
        int beginNum=(pageNumber-1)*pageSize;
		if (proplist.length > 0) {
			str.append("	<tbody >\r");
			String trCssClass="";
			for (int i = 0; i < pageList.size(); i++) {
				trCssClass=i%2==0?"class='even'":"class='odd'";
				str.append("	<tr "+trCssClass+">\r");
				BeanWrapper pageWrapper = new BeanWrapperImpl(pageList.get(i));
				for (int count = 0; count < proplist.length; count++) {
					str.append("		<td "+ cssClasslist[count] + widthlist[count] + alignlist[count] + ">");
					String type = typelist[count];
					String href = hreflist[count];

					String[] formatStrs=formatlist[count].split("&");
					String format = formatStrs[0];

					if (type == null || type.equals("null") || type.equals("")
							|| type.equals("text")) {
						Object data = "";
						if (pageWrapper.isReadableProperty(proplist[count])) {
							data = pageWrapper.getPropertyValue(proplist[count]);
							if (data == null) {
								data = "";
							}

							// format
							if (!format.equals("null")&&!format.equals("")) {

								Object[] formatData=new Object[formatStrs.length];

								formatData[0]=data;

								if(formatStrs.length>1){
									for(int fi=1;fi<formatStrs.length;fi++){
										if(pageWrapper.isReadableProperty(formatStrs[fi])){
											formatData[fi]=pageWrapper.getPropertyValue(formatStrs[fi]);
										}
									}
								}
								data = ReflectionHelper.doFormat(format,formatData);
							}

							// nomal
							if (href.equals("null")) {
								str.append(data);
							} else {
								// href
								String hrefStr = getHrefStr(href,
										paramIdlist[count].split("&"),
										paramPropertylist[count].split("&"),
										pageWrapper);

								str.append("<a href='" + hrefStr + "'>" + data
										+ "</a>");
							}
						}
					}
		    		// checkbox radio
		    		else if(typelist[count].equals("checkbox")||typelist[count].equals("radio")){
		    			String name="";
		    			if(namelist[count].equals("null")==false)
		    			{
		    				name="name='"+namelist[count]+"'";
		    			}
		    			String value="";
		    			if(valuelist[count].equals("null")==false)
		    			{
		    				value="value='"+pageWrapper.getPropertyValue(valuelist[count])+"'";
		    			}
		    			str.append("<input type='"+typelist[count]+"' "+name+" "+value+" />");
		    		}
		    		//serial
		    		else if(typelist[count].equals("serial")){
		    			str.append(beginNum+i+1);
		    		}
		    		str.append("</td>\r");
		    	}
		    	str.append("	</tr>\r");
		    }
			str.append("	</tbody >\r");
		}
	}

	/**
     * リンク文の実施
     */
	private String getHrefStr(String href,String[] paramId,String[] paramProperty,BeanWrapper pageWrapper){
		String hrefStr="";
		String paramIdStr="";
		String paramPropertyStr="";
		for(int pid=0;pid<paramId.length;pid++){
			paramPropertyStr="";
    		if(pageWrapper.isReadableProperty(paramProperty[pid])){
    			Object parObj=pageWrapper.getPropertyValue((String)paramProperty[pid]);
    			if(parObj!=null){
    				paramPropertyStr=parObj.toString();
    			}
    		}
			if(pid==0){
				paramIdStr="?"+paramId[0]+"="+paramPropertyStr;
			}else{
				paramIdStr=paramIdStr+"&"+paramId[pid]+"="+paramPropertyStr;
			}

			hrefStr=href+paramIdStr;
		}
		return hrefStr;
	}

	/**
     *  ページを分ける　action　URLの実施
     */
	private void setActionHtml(String action,boolean hasAction,BaseConditionInfo condi,StringBuilder str){
		if(hasAction){
			//String projectRealPath= Logic.ROOT_PATH;
			String projectRealPath= "";
			if(namespace==null){
				namespace="";
			}
			else{
				namespace+="/";
				if(namespace.startsWith("/")){
					namespace=namespace.substring(1,namespace.length());
				}
			}
			String actStr=action;
			if(action.indexOf(".")>0){
				actStr=action.substring(0,action.indexOf("."));
			}

			String extension=ServletActionContext.getActionMapping().getExtension();

			str.append("<script language='javascript'> \r" +
					   "function "+actStr.replace("-", "_")+"_page(page){\r" +
					   "document.getElementById('"+actStr.replace("-", "_")+"_"+condition+"_page_pageNumber').value=page;\r" +
					   "document.getElementById('"+actStr.replace("-", "_")+"_page').submit();}\r" +
					"</script>\r");

			str.append("<form id='"+actStr.replace("-", "_")+"_page'  action='"+projectRealPath+"/"+namespace+actStr+"."+extension+"' method='post'>\r");
			str.append("	<div id='"+actStr.replace("-", "_")+"_page_con'  style='display:none;'>\r");
			BeanWrapper conditionWrapper = new BeanWrapperImpl(condi);
	    	PropertyDescriptor[] pp=conditionWrapper.getPropertyDescriptors();
	    	for(int ipp=0 ;ipp<pp.length;ipp++){
	    		String cName=pp[ipp].getName();
	    		Object content="";
	    		if(conditionWrapper.getPropertyValue(cName)!=null){
	    			content=conditionWrapper.getPropertyValue(cName);
	    		}
	    		if(!cName.equals("class")){
	    			if(content instanceof java.util.List){
	    				List list=(java.util.List)content;
	    				if(content!=null&&list.size()>0)
	    				for(int i=0;i<list.size();i++){
	    					if(list.get(i)!=null){
	    						str.append("	<input type='hidden' name='"+condition+"."+cName+"["+i+"]' " +
					    				   "value='"+list.get(i).toString()+"' " +
					    				   "id='"+actStr.replace("-", "_")+"_"+condition+"_page_"+cName+i+"'/>\r");
	    					}
	    				}
	    			}else if(content instanceof java.util.Date){
	    				String dateCon=com.sn.system.common.constants.Constants.DATE_FORMAT2.format(content);
	    				str.append("	<input type='hidden' name='"+condition+"."+cName+"' " +
			    				   "value='"+dateCon+"' " +
			    				   "id='"+actStr.replace("-", "_")+"_"+condition+"_page_"+cName+"'/>\r");
	    			}
	    			else{
	    				str.append("	<input type='hidden' name='"+condition+"."+cName+"' " +
			    				   "value='"+content+"' " +
			    				   "id='"+actStr.replace("-", "_")+"_"+condition+"_page_"+cName+"'/>\r");
	    			}
	    		}
	    	}
	    	str.append("	</div>");
	    	//pages
	    	setPageAction(str,actStr);

		}
	}

	/**
     * ページを分けるの実施
     */
	private void setPageAction(StringBuilder str,String actStr){
		//String projectRealPath= Logic.ROOT_PATH;
		String projectRealPath= "";
		Page hpage=(HibernatePage)this.getStack().findValue(page);
			if(hpage!=null){
			if(unit==null)unit="";
			boolean hasnext=hpage.getHasNextPage();
			boolean haspre=hpage.getHasPreviousPage();
			int pageSize=hpage.getPageSize();
	        int totalPage=hpage.getTotalPage();
	        int pageNumber=hpage.getPageNumber();
	        int totalSize=hpage.getTotalSize();
	    	str.append("\r<table id='page_action'><tr><td>");
	    	str.append("検索結果：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;");
	    	if(haspre){
	    		str.append("<a href='javascript:"+actStr.replace("-", "_")+"_page(1)'><img src='"+projectRealPath+"/images/havaFirst.png' border='0'></a>&nbsp;&nbsp;&nbsp;");
	    		str.append("<a href='javascript:"+actStr.replace("-", "_")+"_page("+(pageNumber-1)+")'><img src='"+projectRealPath+"/images/havaPre.png' border='0'></a>&nbsp;&nbsp;&nbsp;");
	    	}
	    	else{
	    		str.append("<img src='"+projectRealPath+"/images/noFirst.png' border='0'>&nbsp;&nbsp;&nbsp;");
	    		str.append("<img src='"+projectRealPath+"/images/noPre.png' border='0'>&nbsp;&nbsp;&nbsp;");
	    	}
	    	if(hasnext){
	    		str.append("<a href='javascript:"+actStr.replace("-", "_")+"_page("+(pageNumber+1)+")'><img src='"+projectRealPath+"/images/havaNext.png' border='0'></a>&nbsp;&nbsp;&nbsp;");
	    		str.append("<a href='javascript:"+actStr.replace("-", "_")+"_page("+totalPage+")'><img src='"+projectRealPath+"/images/havaLast.png' border='0'></a>&nbsp;&nbsp;&nbsp;");
	    	}
	    	else{
	    		str.append("<img src='"+projectRealPath+"/images/noNext.png' border='0'>&nbsp;&nbsp;&nbsp;");
	    		str.append("<img src='"+projectRealPath+"/images/noLast.png' border='0'>&nbsp;&nbsp;&nbsp;");
	    	}
	    	int beginNum=totalSize==0?totalSize:(pageNumber-1)*pageSize+1;
	    	int endNum=totalSize==0?totalSize:beginNum+pageSize-1;
	    	if(totalSize<=endNum)endNum=totalSize;
	    	str.append(beginNum+"~"+endNum);
	    	str.append("/"+totalSize+unit+"中");
	    	str.append("</td></tr></table>\r\r");
		}
	}

	/**
     * 項目名の設定
     */
	private void setHeader(StringBuilder str, String[] titlist ,String[] cssClasslist,String[] widthlist) {
		if(titlist.length>0){
			str.append("	<thead >\r");
			str.append("	<tr>\r");
			for(int i=0;i<titlist.length;i++){
				str.append("		<th "+cssClasslist[i]+ " "+widthlist[i]+">");
				if(!titlist[i].equals("null")){
					str.append(titlist[i]);
				}
				str.append("</th>\r");
			}
			 str.append("	</tr>\r");
			 str.append("	</thead >\r");
		}
	}


	private void pushStack() {
		for(int i=0;i<12;i++){
			this.getStack().push("");
		}
	}

	public String getAction() {
		return action;
	}

	public void setAction(String action) {
		this.action = action;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}
    public String getCondition() {
		return condition;
	}

	public void setCondition(String condition) {
		this.condition = condition;
	}

	public String getUnit() {
		return unit;
	}

	public void setUnit(String unit) {
		this.unit = unit;
	}

	public String getPage() {
		return page;
	}

	public void setPage(String page) {
		this.page = page;
	}

	public String getNamespace() {
		return namespace;
	}

	public void setNamespace(String namespace) {
		this.namespace = namespace;
	}

	public String getCssClass() {
		return cssClass;
	}

	public void setCssClass(String cssClass) {
		this.cssClass = cssClass;
	}

	public String getWidth() {
		return width;
	}

	public void setWidth(String width) {
		this.width = width;
	}

	public String getAlign() {
		return align;
	}

	public void setAlign(String align) {
		this.align = align;
	}


}
